﻿/* Copyright (C) Elisy.Net 2008 http://code.elisy.net
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>. 
*/
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Elisy.Barcode
{
    public class BarcodeEngine
    {
        // Methods
        public string Codabar(string a)
        {
            string s = "";
            for (int i = 0; i < a.Length; i++)
                s = s + this.Code_Char(this.Codabar_Ch(a.Substring(i, 1)));

            return (this.Code_Char(this.Codabar_Ch("d")) + s + this.Code_Char(this.Codabar_Ch("e")));
        }

        private string Codabar_Ch(string ch)
        {
            switch (ch)
            {
                case "0":
                    return "11111331";

                case "1":
                    return "11113311";

                case "2":
                    return "11131131";

                case "3":
                    return "33111111";

                case "4":
                    return "11311311";

                case "5":
                    return "31111311";

                case "6":
                    return "13111131";

                case "7":
                    return "13113111";

                case "8":
                    return "13311111";

                case "9":
                    return "31131111";

                case "-":
                    return "11133111";

                case "$":
                    return "11331111";

                case ":":
                    return "31113131";

                case "/":
                    return "31311131";

                case ".":
                    return "31313111";

                case "+":
                    return "11313131";

                case "a":
                    return "11331111";

                case "b":
                    return "13131131";

                case "c":
                    return "11131331";

                case "d":
                    return "11133311";

                case "t":
                    return "11331311";

                case "n":
                    return "13131131";

                case "*":
                    return "11131331";

                case "e":
                    return "11133311";
            }
            return "";
        }

        public string Code128(string a)
        {
            int[] bCode = new int[0x400];
            int bInd = 0;
            string curMode = "";
            int i = 0;
            int lenA = a.Length;
            while (i < lenA)
            {
                byte ch = (byte)a[i];
                i++;
                if (ch <= 127)
                {
                    byte ch2;
                    if (i < lenA)
                        ch2 = (byte)a[i];
                    else
                        ch2 = 0;

                    if ((((0x30 <= ch) & (ch <= 0x39)) & (0x30 <= ch2)) & (ch2 <= 0x39))
                    {
                        i++;
                        if (bInd == 0)
                        {
                            curMode = "C";
                            bCode[bInd] = 0x69;
                            bInd++;
                        }
                        else if (curMode != "C")
                        {
                            curMode = "C";
                            bCode[bInd] = 0x63;
                            bInd++;
                        }
                        bCode[bInd] = Convert.ToInt16(string.Format("{0}{1}", (char)ch, (char)ch2));
                        bInd++;
                    }
                    else
                    {
                        if (bInd == 0)
                        {
                            if (ch < 0x20)
                            {
                                curMode = "A";
                                bCode[bInd] = 0x67;
                                bInd++;
                            }
                            else
                            {
                                curMode = "B";
                                bCode[bInd] = 0x68;
                                bInd++;
                            }
                        }
                        if ((ch < 0x20) & (curMode != "A"))
                        {
                            curMode = "A";
                            bCode[bInd] = 0x65;
                            bInd++;
                        }
                        else if (((0x40 <= ch) & (curMode != "B")) | (curMode == "C"))
                        {
                            curMode = "B";
                            bCode[bInd] = 100;
                            bInd++;
                        }
                        if (ch < 0x20)
                        {
                            bCode[bInd] = ch + 0x40;
                            bInd++;
                        }
                        else
                        {
                            bCode[bInd] = ch - 0x20;
                            bInd++;
                        }
                    }
                }
            }
            int cCode = bCode[0] % 0x67;
            for (i = 1; i <= bInd - 1; i++)
                cCode = (cCode + (bCode[i] * i)) % 0x67;
            bCode[bInd] = cCode;
            bInd++;
            bCode[bInd] = 0x6a;
            bInd++;
            string[] barArray = new string[] { 
                "155", "515", "551", "449", "485", "845", "458", "494", "854", "548", "584", "944", "056", "416", "452", "065", 
                "425", "461", "560", "506", "542", "164", "524", "212", "245", "605", "641", "254", "614", "650", "119", "191", 
                "911", "089", "809", "881", "098", "818", "890", "188", "908", "980", "01:", "092", "812", "029", "0:1", "821", 
                "221", "182", "902", "128", "1:0", "122", "209", "281", ":01", "218", "290", ":10", "230", "5<0", ";00", "04=", 
                "0<5", "40=", "4<1", "<05", "<41", "05<", "0=4", "41<", "4=0", "<14", "<50", "=40", "50<", "320", "=04", "830", 
                "047", "407", "443", "074", "434", "470", "344", "704", "740", "113", "131", "311", "00;", "083", "803", "038", 
                "0;0", "308", "380", "023", "032", "203", "302", "A", "B", "C", "@"
             };
            string s = "";
            for (i = 0; i <= bInd - 1; i++)
                s = s + this.Code_Char(this.Code_128_ID(bCode[i]));

            return s;
        }

        private string Code_128_ID(int id)
        {
            string s = "";
            switch (id)
            {
                case 0:
                    return "212222";

                case 1:
                    return "222122";

                case 2:
                    return "222221";

                case 3:
                    return "121223";

                case 4:
                    return "121322";

                case 5:
                    return "131222";

                case 6:
                    return "122213";

                case 7:
                    return "122312";

                case 8:
                    return "132212";

                case 9:
                    return "221213";

                case 10:
                    return "221312";

                case 11:
                    return "231212";

                case 12:
                    return "112232";

                case 13:
                    return "122132";

                case 14:
                    return "122231";

                case 15:
                    return "113222";

                case 0x10:
                    return "123122";

                case 0x11:
                    return "123221";

                case 0x12:
                    return "223211";

                case 0x13:
                    return "221132";

                case 20:
                    return "221231";

                case 0x15:
                    return "213212";

                case 0x16:
                    return "223112";

                case 0x17:
                    return "312131";

                case 0x18:
                    return "311222";

                case 0x19:
                    return "321122";

                case 0x1a:
                    return "321221";

                case 0x1b:
                    return "312212";

                case 0x1c:
                    return "322112";

                case 0x1d:
                    return "322211";

                case 30:
                    return "212123";

                case 0x1f:
                    return "212321";

                case 0x20:
                    return "232121";

                case 0x21:
                    return "111323";

                case 0x22:
                    return "131123";

                case 0x23:
                    return "131321";

                case 0x24:
                    return "112313";

                case 0x25:
                    return "132113";

                case 0x26:
                    return "132311";

                case 0x27:
                    return "211313";

                case 40:
                    return "231113";

                case 0x29:
                    return "231311";

                case 0x2a:
                    return "112133";

                case 0x2b:
                    return "112331";

                case 0x2c:
                    return "132131";

                case 0x2d:
                    return "113123";

                case 0x2e:
                    return "113321";

                case 0x2f:
                    return "133121";

                case 0x30:
                    return "313121";

                case 0x31:
                    return "211331";

                case 50:
                    return "231131";

                case 0x33:
                    return "213113";

                case 0x34:
                    return "213311";

                case 0x35:
                    return "213131";

                case 0x36:
                    return "311123";

                case 0x37:
                    return "311321";

                case 0x38:
                    return "331121";

                case 0x39:
                    return "312113";

                case 0x3a:
                    return "312311";

                case 0x3b:
                    return "332111";

                case 60:
                    return "314111";

                case 0x3d:
                    return "221411";

                case 0x3e:
                    return "431111";

                case 0x3f:
                    return "111224";

                case 0x40:
                    return "111422";

                case 0x41:
                    return "121124";

                case 0x42:
                    return "121421";

                case 0x43:
                    return "141122";

                case 0x44:
                    return "141221";

                case 0x45:
                    return "112214";

                case 70:
                    return "112412";

                case 0x47:
                    return "122114";

                case 0x48:
                    return "122411";

                case 0x49:
                    return "142112";

                case 0x4a:
                    return "142211";

                case 0x4b:
                    return "241211";

                case 0x4c:
                    return "221114";

                case 0x4d:
                    return "413111";

                case 0x4e:
                    return "241112";

                case 0x4f:
                    return "134111";

                case 80:
                    return "111242";

                case 0x51:
                    return "121142";

                case 0x52:
                    return "121241";

                case 0x53:
                    return "114212";

                case 0x54:
                    return "124112";

                case 0x55:
                    return "124211";

                case 0x56:
                    return "411212";

                case 0x57:
                    return "421112";

                case 0x58:
                    return "421211";

                case 0x59:
                    return "212141";

                case 90:
                    return "214121";

                case 0x5b:
                    return "412121";

                case 0x5c:
                    return "111143";

                case 0x5d:
                    return "111341";

                case 0x5e:
                    return "131141";

                case 0x5f:
                    return "114113";

                case 0x60:
                    return "114311";

                case 0x61:
                    return "411113";

                case 0x62:
                    return "411311";

                case 0x63:
                    return "113141";

                case 100:
                    return "114131";

                case 0x65:
                    return "311141";

                case 0x66:
                    return "411131";

                case 0x67:
                    return "211412";

                case 0x68:
                    return "211214";

                case 0x69:
                    return "211232";

                case 0x6a:
                    return "2331112";
            }
            return s;
        }

        private string Code_2of5_Ch(string ch)
        {
            switch (ch)
            {
                case "0":
                    return "11331";

                case "1":
                    return "31113";

                case "2":
                    return "13113";

                case "3":
                    return "33111";

                case "4":
                    return "11313";

                case "5":
                    return "31311";

                case "6":
                    return "13311";

                case "7":
                    return "11133";

                case "8":
                    return "31131";

                case "9":
                    break;
            }
            return "13131";
        }

        public string Code39(string a)
        {
            string s = "";
            for (int i = 0; i < a.Length; i++)
                s = s + this.Code_Char(this.Code_39_Ch(a.Substring(i, 1)));

            return (this.Code_Char(this.Code_39_Ch("*")) + s + this.Code_Char(this.Code_39_Ch("*")));
        }

        private string Code_39_Ch(string ch)
        {
            switch (ch)
            {
                case "1":
                    return "3113111131";

                case "2":
                    return "1133111131";

                case "3":
                    return "3133111111";

                case "4":
                    return "1113311131";

                case "5":
                    return "3113311111";

                case "6":
                    return "1133311111";

                case "7":
                    return "1113113131";

                case "8":
                    return "3113113111";

                case "9":
                    return "1133113111";

                case "0":
                    return "1113313111";

                case "A":
                    return "3111131131";

                case "B":
                    return "1131131131";

                case "C":
                    return "3131131111";

                case "D":
                    return "1111331131";

                case "E":
                    return "3111331111";

                case "F":
                    return "1131331111";

                case "G":
                    return "1111133131";

                case "H":
                    return "3111133111";

                case "I":
                    return "1131133111";

                case "J":
                    return "1111333111";

                case "K":
                    return "3111111331";

                case "L":
                    return "1131111331";

                case "M":
                    return "3131111311";

                case "N":
                    return "1111311331";

                case "O":
                    return "3111311311";

                case "P":
                    return "1131311311";

                case "Q":
                    return "1111113331";

                case "R":
                    return "3111113311";

                case "S":
                    return "1131113311";

                case "T":
                    return "1111313311";

                case "U":
                    return "3311111131";

                case "V":
                    return "1331111131";

                case "W":
                    return "3331111111";

                case "X":
                    return "1311311131";

                case "Y":
                    return "3311311111";

                case "Z":
                    return "1331311111";

                case "-":
                    return "1311113131";

                case ".":
                    return "3311113111";

                case " ":
                    return "1331113111";

                case "*":
                    return "1311313111";

                case "$":
                    return "1313131111";

                case "/":
                    return "1313111311";

                case "+":
                    return "1311131311";

                case "%":
                    return "1113131311";
            }
            return "";
        }

        private string Code_Char(string a)
        {
            switch (a)
            {
                case "211412":
                    return "A";

                case "211214":
                    return "B";

                case "211232":
                    return "C";

                case "2331112":
                    return "@";
            }
            string s = "";
            int endValue = (int) Math.Round((double) ((((double) a.Length) / 2.0) - 1.0));
            for (int i = 0; i <= endValue; i++)
            {
                switch (a.Substring((2 * i), 2))
                {
                    case "11":
                        s = s + "0";
                        break;

                    case "21":
                        s = s + "1";
                        break;

                    case "31":
                        s = s + "2";
                        break;

                    case "41":
                        s = s + "3";
                        break;

                    case "12":
                        s = s + "4";
                        break;

                    case "22":
                        s = s + "5";
                        break;

                    case "32":
                        s = s + "6";
                        break;

                    case "42":
                        s = s + "7";
                        break;

                    case "13":
                        s = s + "8";
                        break;

                    case "23":
                        s = s + "9";
                        break;

                    case "33":
                        s = s + ":";
                        break;

                    case "43":
                        s = s + ";";
                        break;

                    case "14":
                        s = s + "<";
                        break;

                    case "24":
                        s = s + "=";
                        break;

                    case "34":
                        s = s + ">";
                        break;

                    case "44":
                        s = s + "?";
                        break;
                }
            }
            return s;
        }

        public string Interleaved2of5(string a, bool check)
        {
            int i;
            string d = "";
            for (i = 0; i < a.Length; i++)
            {
                byte ch = (byte)a[i];
                if ((0x30 <= ch) & (ch <= 0x39))
                    d = d + a[i];
            }

            if ((((d.Length % 2) > 0) & !check) | (((d.Length % 2) == 0) & check))
                d = "0" + d;

            if (check)
            {
                int k = 0;
                for (i = 0; i < d.Length; i++)
                {
                    if ((i % 2) > 0)
                        k += Convert.ToInt16(d.Substring(i, 1)) * 3;
                    else
                        k += Convert.ToInt16(d.Substring(i, 1));
                }
                k = 10 - (k % 10);
                d = d + k.ToString();
            }
            string s = "";
            int endValue = (int) Math.Round((double)(d.Length / 2 - 1));
            for (i = 0; i <= endValue; i++)
                s = s + this.Code_Char(this.Interleaved_2of5_Pair(d.Substring(i * 2, 2)));

            return (this.Code_Char("1111") + s + this.Code_Char("3111"));
        }

        private string Interleaved_2of5_Pair(string pair)
        {
            string s1 = this.Code_2of5_Ch(pair.Substring(0, 1));
            string s2 = this.Code_2of5_Ch(pair.Substring(1, 1));
            string s = "";
            for (int i = 0; i < s1.Length; i++)
                s = s + s1.Substring(i, 1) + s2.Substring(i, 1);

            return s;
        }
    }
}
